package com.dingreading.cloud.common.util.wechat;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.DateUtil;
import com.dingreading.cloud.common.util.EnumType;
import com.dingreading.cloud.common.util.HttpUtils;
import com.dingreading.cloud.common.util.IpUtil;
import org.apache.commons.lang3.StringUtils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 微信支付回调方法
 */
public class WxPayBusiness {

    private WxPayBusiness() {
    }

    private static class Instance {
        private static final WxPayBusiness wxPayBusiness = new WxPayBusiness();

        private static WxPayBusiness getWxPayBusiness() {
            return wxPayBusiness;
        }
    }

    public static WxPayBusiness Init() {
        return Instance.getWxPayBusiness();
    }


    /**
     * 小程序统一下单
     *
     * @param miniAppId 小程序appID
     * @param map       订单map
     * @param request   request
     * @return Map
     */
    public Map<String, String> miniUnifiedOrderBusiness(
            HttpServletRequest request,
            Map<String, String> map, String miniAppId, String mckId, String mchKey, String notifyUrl
    ) throws Exception {
        Map<String, String> result = new HashMap<>();
        String code = map.get("OutTradeNo");
        String tradeType = map.get("tradeType");
        // 获取统一下单后的参数
        Map<String, String> resultMap = miniUnifiedOrder(request, miniAppId, mckId, mchKey, map, notifyUrl);
        if (null == resultMap) {
            throw new Exception("微信统一下单失败，resultMap空，订单编号:" + code);
        }
        // 通信标识
        String returnCode = resultMap.get("return_code");
        // 交易标识
        String resultCode = resultMap.get("result_code");

        // 只有当returnCode与resultCode均返回success，才代表微信支付统一下单成功
        if (PayConfig.RETURN_SUCCESS.equals(resultCode) && PayConfig.RETURN_SUCCESS.equals(returnCode)) {
            if (tradeType.equals(EnumType.TradeType.WECHAT_NATIVE.getType())) {
                // 扫码支付
                String codeUrl = resultMap.get("code_url");
                result.put("code_url", codeUrl);
            }
            // 微信公众号AppId
            String appId = resultMap.get("appid");
            // 当前时间戳
            String timeStamp = WxDataUtils.getTimeStamp();
            // 统一下单返回的预支付id
            String prepayId = "prepay_id=" + resultMap.get("prepay_id");
            // 不长于32位的随机字符串
            String nonceStr = WxDataUtils.getRandomStr(32);
            // 自然升序map
            SortedMap<String, String> signMap = new TreeMap<>();
            signMap.put("appId", appId);
            signMap.put("package", prepayId);
            signMap.put("timeStamp", timeStamp);
            signMap.put("nonceStr", nonceStr);
            signMap.put("signType", "MD5");

            result.put("appId", appId);
            result.put("timeStamp", timeStamp);
            result.put("nonceStr", nonceStr);
            result.put("package", prepayId);
            result.put("signType", "MD5");
            // 获取签名
            result.put("paySign", WxDataUtils.createSign(signMap, mchKey));
        } else {
            throw new Exception("微信统一下单失败,订单编号:" + code + ",失败原因:" + resultMap.get("return_msg"));
        }
        return result;
    }

    /**
     * 小程序支付-统一下单处理
     *
     * @param miniAppId 小程序appId
     * @param map       请求参数
     * @return Map
     */
    private Map<String, String> miniUnifiedOrder(
            HttpServletRequest request,
            String miniAppId, String mckId, String mchKey, Map<String, String> map, String notifyUrl
    ) throws Exception {
        String code = map.get("OutTradeNo");
        String fee = map.get("fee");
        String tradeType = map.get("tradeType");
        String body = map.get("body");
        int totalFee = WxDataUtils.formatDoubleTOInt(Double.parseDouble(fee), 100.0);
        SortedMap<String, String> resultMap;
        try {
            WxPaySendData paySendData = new WxPaySendData();
            // 构建微信支付请求参数集合
            // 小程序账号ID
            paySendData.setAppId(miniAppId);
            // 商户号
            paySendData.setMchId(mckId);
            // 过期时间 24小时
            String expireTime = getExpireTime();
            paySendData.setTimeExpire(expireTime);
            // 随机字符串
            paySendData.setNonceStr(UUID.randomUUID().toString().replaceAll("-", ""));
            paySendData.setBody(body);
            // 商户订单号
            paySendData.setOutTradeNo(code);
            // 标价金额，订单总金额，单位为分
            paySendData.setTotalFee(totalFee);
            // 终端IP
            paySendData.setSpBillCreateIp(IpUtil.getIpAddr(request));
            // 微信支付成功后回调通知地址
            paySendData.setNotifyUrl(PayConfig.getWxNotifyUrl(notifyUrl));
            // 交易类型
            paySendData.setTradeType(tradeType);
            // 用户标识，小程序支付时必填
            if (StringUtils.isNotBlank(tradeType) && tradeType.equals(EnumType.TradeType.WECHAT_JSAPI.getType())) {
                String openid = map.get("openid");
                paySendData.setOpenId(openid);
            }
            // 选填 设备号
            paySendData.setDeviceInfo("WEB");
            // 附件参数
            paySendData.setAttach(map.get("attach"));

            // 将参数拼成map，生成签名
            SortedMap<String, String> params = buildParamMap(paySendData);
            // 签名
            paySendData.setSign(WxDataUtils.createSign(params, mchKey));
            // 将请求参数对象转换成xml
            String reqXml = WxDataUtils.sendDataToXml(paySendData);

            // 发送请求
            String result = HttpUtils.post(PayConfig.UNIFIED_ORDER_URL, reqXml);
            resultMap = WxDataUtils.xml2Map(result);
        } catch (Exception e) {
            throw new Exception(e);
        }
        return resultMap;
    }

    /**
     * 支付成功后的签名认证处理
     *
     * @param response 返回
     * @return map
     * @throws Exception 异常
     */
    public SortedMap<String, String> paySuccess(HttpServletResponse response, SortedMap<String, String> resultMap, String mchKey) throws Exception {

        // 回调后返回给微信的结果，不返回微信会回调多次
        String result = "";
        if (resultMap != null && resultMap.size() > 0) {
            String signReceive = resultMap.get("sign");
            // 去掉sign，获取签名再对比
            resultMap.remove("sign");
            String checkSign = WxDataUtils.getSign(resultMap, mchKey);
            // 签名校验成功
            if (checkSign != null && signReceive != null && checkSign.equals(signReceive.trim())) {

                String returnCode = resultMap.get("return_code");
                String resultCode = resultMap.get("result_code");
                // 支付成功
                if (PayConfig.RETURN_SUCCESS.equals(returnCode) && PayConfig.RETURN_SUCCESS.equals(resultCode)) {
//                    System.out.println("微信支付成功，out_trade_no(erpId_ordId)：" + resultMap.get("out_trade_no"));
                    result = PayConfig.PAY_SUCCESS_RETURN_MSG;
                    resultMap.put("success", "success");
                } else {
//                    System.out.println("微信支付失败，return_msg：" + returnMsg);
                    result = String.format(PayConfig.SIGN_FAIL_RETURN_MSG, resultMap.get("return_msg"));
                }
            } else {
                // 签名校验失败
                System.out.println("微信支付签名校验失败");
                result = String.format(PayConfig.SIGN_FAIL_RETURN_MSG, "check sign fail");
            }
        }

        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/xml");
        response.getWriter().write(result);
        response.getWriter().flush();
        response.getWriter().close();
        return resultMap;
    }

    /**
     * 微信小程序关闭订单
     *
     * @param miniId 微信分配的小程序ID
     * @param mchId  商户id
     * @param mchKey 商户key
     * @param code   订单号
     * @return obj
     * @throws Exception 异常
     */
    public JSONObject miniCloseOrder(String miniId, String mchId, String mchKey, String code) throws Exception {
        JSONObject jsonObject;
        try {
            Map<String, String> packageParams = new HashMap<>();
            packageParams.put("appid", miniId);
            packageParams.put("mch_id", mchId);
            packageParams.put("out_trade_no", code);
            packageParams.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));
            String sign = PaymentKit.createSign(packageParams, mchKey);
            packageParams.put("sign", sign);
            // 将请求参数对象转换成xml
            String reqXml = PaymentKit.toXml(packageParams);
            String result = HttpUtils.post(PayConfig.CLOSE_ORDER_URL, reqXml);
            SortedMap<String, String> resultMap = WxDataUtils.xml2Map(result);
            jsonObject = new JSONObject();
            String result_code = resultMap.get("result_code");
            String result_msg = resultMap.get("result_msg");
            jsonObject.put("result_code", result_code);
            jsonObject.put("result_msg", result_msg);
            jsonObject.put("code", code);
        } catch (Exception e) {
            throw new Exception(e);
        }
        return jsonObject;
    }

    /**
     * 请求退款
     *
     * @param data     微信map参数
     * @param certPath 证书物理路径
     * @param certPass 证书密码,默认为商户id
     * @return {String}
     */
    public static Map<String, String> orderRefund(String data, String certPath, String certPass) {
        Map<String, String> resultMap = new HashMap<>();
        try {
            String refundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
            byte[] xmlData = data.getBytes();
            // 读取微信证书格式为PKCS12
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            // 指定PKCS12的密码(商户ID)读取本机存放的PKCS12证书文件
            keyStore.load(new FileInputStream(certPath), certPass.toCharArray());
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(keyStore, certPass.toCharArray());
            KeyManager[] kms = kmf.getKeyManagers();
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(kms, null, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

            URL url = new URL(refundUrl);
            HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
            urlConnection.setConnectTimeout(25000);
            urlConnection.setReadTimeout(25000);
            urlConnection.setRequestMethod("POST");
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
            urlConnection.setRequestProperty("Content-length", String.valueOf(xmlData.length));
            DataOutputStream outputStream = new DataOutputStream(urlConnection.getOutputStream());
            outputStream.write(xmlData);
            outputStream.flush();
            outputStream.close();
            resultMap = WxDataUtils.parseXml(urlConnection.getInputStream());

        } catch (Exception e) {
            System.out.println(e);
            return resultMap;
        }
        return resultMap;
    }

    /**
     * 公众号支付-统一下单
     *
     * @param map map
     * @return Map
     */
    public R<Object> unifiedOrderBusiness(
            HttpServletRequest request,
            Map<String, String> map, String appId, String appSecret, String mchId, String mchKey, String notifyUrl
    ) throws Exception {
//        System.out.println("appId = " + appId);
//        System.out.println("appSecret = " + appSecret);
//        System.out.println("mchId = " + mchId);
//        System.out.println("mchKey = " + mchKey);
        // 获取统一下单后的参数
        Map<String, String> resultMap = unifiedOrder(request, map, appId, appSecret, mchId, mchKey, notifyUrl);

//        System.out.println("微信支付统一下单结果 = \n" + resultMap.toString());
        if (null == resultMap) {
            return R.fail("微信统一下单失败，resultMap空，订单编号:" + map.get("OutTradeNo"));
        }
        // 通信标识
        String returnCode = resultMap.get("return_code");
        // 交易标识
        String resultCode = resultMap.get("result_code");
        // 错误码描述
        String errCodeDes = resultMap.get("err_code_des");

        Map<String, String> result = new HashMap<>();
        // 只有当returnCode与resultCode均返回success，才代表微信支付统一下单成功
        if (PayConfig.RETURN_SUCCESS.equals(resultCode) && PayConfig.RETURN_SUCCESS.equals(returnCode)) {
            // 微信公众号AppId
            String appId2 = resultMap.get("appid");
            // 当前时间戳
            String timeStamp = WxDataUtils.getTimeStamp();
            // 统一下单返回的预支付id
            String prepayId = "prepay_id=" + resultMap.get("prepay_id");
            // 不长于32位的随机字符串
            String nonceStr = WxDataUtils.getRandomStr(32);
            // 自然升序map
            SortedMap<String, String> signMap = new TreeMap<>();
            signMap.put("appId", appId2);
            signMap.put("package", prepayId);
            signMap.put("timeStamp", timeStamp);
            signMap.put("nonceStr", nonceStr);
            signMap.put("signType", "MD5");

            result.put("appId", appId2);
            result.put("timeStamp", timeStamp);
            result.put("nonceStr", nonceStr);
            result.put("prepayId", prepayId);
            result.put("signType", "MD5");
            // 获取签名
            result.put("paySign", WxDataUtils.createSign(signMap, mchKey));
            if (StringUtils.isNotBlank(map.get("tradeType")) && map.get("tradeType").equals(EnumType.TradeType.WECHAT_NATIVE.getType())) {
                // 扫码支付
                String codeUrl = resultMap.get("code_url");
                result.put("code_url", codeUrl);
                return R.ok(codeUrl);
            } else {
                return R.ok(result);
            }
        } else {
            return R.fail("微信统一下单失败,订单编号:" + map.get("OutTradeNo") + ",失败原因:" + errCodeDes);
        }
    }

    /**
     * 公众号支付-统一下单处理
     *
     * @param map msp
     * @return Map
     */
    private Map<String, String> unifiedOrder(
            HttpServletRequest request, Map<String, String> map, String appId, String appSecret, String mchId, String mchKey,
            String notifyUrl
    ) throws Exception {
        int totalFee = WxDataUtils.formatDoubleTOInt(Double.parseDouble(map.get("fee")), 100.0);
        Map<String, String> resultMap;
        try {
            WxPaySendData paySendData = new WxPaySendData();
            // 构建微信支付请求参数集合
            // 必填
            // 公众账号ID
            paySendData.setAppId(appId);
            // 商户号
            paySendData.setMchId(mchId);
            // 随机字符串
            paySendData.setNonceStr(UUID.randomUUID().toString().replaceAll("-", ""));
            paySendData.setBody(map.get("body"));
            // 商户订单号
            paySendData.setOutTradeNo(map.get("OutTradeNo"));
            // 标价金额，订单总金额，单位为分
            paySendData.setTotalFee(totalFee);
            // 订单失效时间，5分钟后
            Date date = DateUtil.addMinutes(new Date(), 30);
            String timeExpire = DateUtil.getDefaultDateFulltime(date);
            paySendData.setTimeExpire(timeExpire);
            // 终端IP
            paySendData.setSpBillCreateIp(IpUtil.getIpAddr(request));
            // 微信支付成功后回调通知地址
            paySendData.setNotifyUrl(PayConfig.getWxNotifyUrl(notifyUrl));
//            System.out.println("paySendData.getNotifyUrl() = " + paySendData.getNotifyUrl());
            // 交易类型
            if (map.get("tradeType").equals(EnumType.TradeType.WECHAT_NATIVE.getType())) {
                paySendData.setTradeType(map.get("tradeType"));
            } else if (map.get("tradeType").equals(EnumType.TradeType.WECHAT_JSAPI.getType())) {
                paySendData.setTradeType(map.get("tradeType"));
                if (StringUtils.isNotEmpty(map.get("code"))) {
                    AuthToken authToken = getAccessToken(map.get("code"), appId, appSecret);
                    // 用户标识，jsapi支付时必填
                    paySendData.setOpenId(authToken.getOpenid());
                } else {
                    // 用户标识，jsapi支付时必填
                    paySendData.setOpenId(map.get("openid"));
                }
            }
            // 选填 设备号
            paySendData.setDeviceInfo("WEB");

            // 附件参数
            paySendData.setAttach(map.get("attach"));

            // 将参数拼成map，生成签名
            SortedMap<String, String> params = buildParamMap(paySendData);
            // 签名
            paySendData.setSign(WxDataUtils.createSign(params, mchKey));

            // 将请求参数对象转换成xml
            String reqXml = WxDataUtils.sendDataToXml(paySendData);
            // 发送请求
            byte[] xmlData = reqXml.getBytes(StandardCharsets.UTF_8);
            URL url = new URL(PayConfig.UNIFIED_ORDER_URL);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            urlConnection.setRequestProperty("Content_Type", "text/xml");
            urlConnection.setRequestProperty("Content-length", String.valueOf(xmlData.length));
            DataOutputStream outputStream = new DataOutputStream(urlConnection.getOutputStream());
            outputStream.write(xmlData);
            outputStream.flush();
            outputStream.close();
            resultMap = WxDataUtils.parseXml(urlConnection.getInputStream());
        } catch (Exception e) {
            throw new Exception(e);
        }
        return resultMap;
    }

    /**
     * H5支付-统一下单处理
     *
     * @param map map
     * @return String
     */
    public R<Object> h5UnifiedOrder(
            HttpServletRequest request,
            Map<String, String> map, String appId, String mchId, String mchKey, String notifyUrl
    ) throws Exception {
        Map<String, String> resultMap;
        int totalFee = WxDataUtils.formatDoubleTOInt(Double.parseDouble(map.get("fee")), 100.0);
        try {
            WxPaySendData paySendData = new WxPaySendData();
            // 构建微信支付请求参数集合
            // 公众账号ID
            paySendData.setAppId(appId);
            // 商户号
            paySendData.setMchId(mchId);
            // 随机字符串
            paySendData.setNonceStr(UUID.randomUUID().toString().replaceAll("-", ""));
            paySendData.setBody(map.get("body"));
            // 商户订单号
            paySendData.setOutTradeNo(map.get("OutTradeNo"));
            // 标价金额，订单总金额，单位为分
            paySendData.setTotalFee(totalFee);
            // 终端IP
            paySendData.setSpBillCreateIp(IpUtil.getIpAddr(request));
            // 微信支付成功后回调通知地址
            paySendData.setNotifyUrl(PayConfig.getWxNotifyUrl(notifyUrl));
            // 交易类型 H5 支付
            paySendData.setTradeType("MWEB");
            // H5支付专用
            JSONObject value = new JSONObject();
            value.put("type", "Wap");
            // //WAP网站URL地址
            value.put("wap_url", "http://www.dingreading.com");
            // WAP 网站名
            value.put("wap_name", "叮叮书房");
            JSONObject sceneInfo = new JSONObject();
            sceneInfo.put("h5_info", value);
            paySendData.setSceneInfo(sceneInfo.toString());
            // 选填 设备号
            paySendData.setDeviceInfo("WEB");
            // 附件参数
            paySendData.setAttach(map.get("attach"));

            // 将参数拼成map，生成签名
            SortedMap<String, String> params = buildParamMap(paySendData);
            // 签名
            paySendData.setSign(WxDataUtils.createSign(params, mchKey));

            // 将请求参数对象转换成xml
            String reqXml = WxDataUtils.sendDataToXml(paySendData);
//            System.out.println("微信H5支付统一下单请求参数：\n" + reqXml);
            // 发送请求
            byte[] xmlData = reqXml.getBytes(StandardCharsets.UTF_8);
            URL url = new URL(PayConfig.UNIFIED_ORDER_URL);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            urlConnection.setRequestProperty("Content_Type", "text/xml");
            urlConnection.setRequestProperty("Content-length", String.valueOf(xmlData.length));
            DataOutputStream outputStream = new DataOutputStream(urlConnection.getOutputStream());
            outputStream.write(xmlData);
            outputStream.flush();
            outputStream.close();
            resultMap = WxDataUtils.parseXml(urlConnection.getInputStream());
//            System.out.println("微信H5支付统一下单请求结果 = \n" + resultMap);

            String returnCode = resultMap.get("return_code");
            if ("SUCCESS".equals(returnCode)) {
                String resultCode = resultMap.get("result_code");
                if ("SUCCESS".equals(resultCode)) {
                    return R.ok(resultMap.get("mweb_url"));
                } else {
                    return R.fail(resultMap.get("err_code_des"));
                }
            } else {
                return R.fail(resultMap.get("return_msg"));
            }
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
    }

    /**
     * 微信扫码回调接口
     *
     * @param reqXml 微信map参数
     * @return {String}
     */
    public static Map<String, String> scanCode(String reqXml) {
        Map<String, String> resultMap = new HashMap<>();
        try {
            byte[] xmlData = reqXml.getBytes(StandardCharsets.UTF_8);
            URL url = new URL(PayConfig.UNIFIED_ORDER_URL);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setDoOutput(true);
            urlConnection.setDoInput(true);
            urlConnection.setUseCaches(false);
            urlConnection.setRequestProperty("Content_Type", "text/xml");
            urlConnection.setRequestProperty("Content-length", String.valueOf(xmlData.length));
            DataOutputStream outputStream = new DataOutputStream(urlConnection.getOutputStream());
            outputStream.write(xmlData);
            outputStream.flush();
            outputStream.close();
            resultMap = WxDataUtils.parseXml(urlConnection.getInputStream());
        } catch (Exception e) {
            return resultMap;
        }
        return resultMap;
    }

    /**
     * 设置微信二维码失效时间，并返回具体失效的时间点
     *
     * @return string
     */
    private static String getExpireTime() {
        //二维码的有效时间，单位是毫秒
        long expire = 24 * 60 * 60 * 1000L;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        Date now = new Date();
        Date afterDate = new Date(now.getTime() + expire);
        return sdf.format(afterDate);
    }

    /**
     * 构建统一下单参数map 用于生成签名
     *
     * @param data data
     * @return SortedMap<String>
     */
    private SortedMap<String, String> buildParamMap(WxPaySendData data) {
        SortedMap<String, String> paramters = new TreeMap<>();
        if (null != data) {
            if (StringUtils.isNotEmpty(data.getAppId())) {
                paramters.put("appid", data.getAppId());
            }
            if (StringUtils.isNotEmpty(data.getMchId())) {
                paramters.put("mch_id", data.getMchId());
            }
            if (StringUtils.isNotEmpty(data.getDeviceInfo())) {
                paramters.put("device_info", data.getDeviceInfo());
            }
            if (StringUtils.isNotEmpty(data.getNonceStr())) {
                paramters.put("nonce_str", data.getNonceStr());
            }
            if (StringUtils.isNotEmpty(data.getBody())) {
                paramters.put("body", data.getBody());
            }
            if (StringUtils.isNotEmpty(data.getOutTradeNo())) {
                paramters.put("out_trade_no", data.getOutTradeNo());
            }
            if (data.getTotalFee() > 0) {
                paramters.put("total_fee", data.getTotalFee() + "");
            }
            if (StringUtils.isNotEmpty(data.getSpBillCreateIp())) {
                paramters.put("spbill_create_ip", data.getSpBillCreateIp());
            }
            if (StringUtils.isNotEmpty(data.getTimeExpire())) {
                paramters.put("time_expire", data.getTimeExpire());
            }
            if (StringUtils.isNotEmpty(data.getTradeType())) {
                paramters.put("trade_type", data.getTradeType());
            }
            if (StringUtils.isNotEmpty(data.getNotifyUrl())) {
                paramters.put("notify_url", data.getNotifyUrl());
            }
            if (StringUtils.isNotEmpty(data.getOpenId())) {
                paramters.put("openid", data.getOpenId());
            }
            if (StringUtils.isNotEmpty(data.getSceneInfo())) {
                paramters.put("scene_info", data.getSceneInfo());
            }
            if (StringUtils.isNotEmpty(data.getAttach())) {
                paramters.put("attach", data.getAttach());
            }

        }
        return paramters;
    }

    /**
     * 获取基础接口access_token。
     *
     * @return 微信访问Token字符串。
     */
    public String getAccessToken(String appId, String appSecret) {
        String url = String.format(PayConfig.GET_ACCESS_TOKEN_URL, appId, appSecret);
        String result = HttpUtils.get(url);
        JSONObject jsonObject = JSON.parseObject(result);
        String accessToken = jsonObject.getString("access_token");
        if (StringUtils.isNotBlank(accessToken))
            return accessToken;

        System.out.println("获取微信访问Token失败！微信服务器返回的数据为：{}" + result);
        return "";
    }

    /**
     * 获取网页授权的access_token
     */
    public AuthToken getAccessToken(String code, String appId, String appSecret) throws Exception {
        AuthToken authToken;

        // 通过code获取网页授权access_token
        try {
            authToken = getTokenByAuthCode(code, appId, appSecret);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("获取access_token异常");
            throw new Exception("获取access_token异常");
        }
        if (null == authToken) {
            System.out.println("获取access_token异常，authToken空值");
            throw new Exception("获取access_token异常，authToken空值");
        }
//        System.out.println("微信支付获取获取网页授权end，authToken：" + authToken);
        return authToken;
    }

    private AuthToken getTokenByAuthCode(String code, String appId, String appSecret) throws Exception {
        AuthToken authToken = null;
        String requestUrl = PayConfig.GET_AUTHTOKEN_URL + "appid=" + appId + "&secret="
                + appSecret + "&code=" + code + "&grant_type=authorization_code";
        String json = HttpUtils.get(requestUrl);
//        System.out.println("公众号：" + code + "，获取网页授权accessToken = " + json);
        if (StringUtils.isNotBlank(json)) {
            authToken = JSONObject.parseObject(json, AuthToken.class);
        }
        return authToken;
    }

}
